/*
* Copyright (c) 2007 by Kirill Kolodyazhniy.
* See the file "license.terms" for information on usage and redistribution.
*/

#ifndef M_SHADOWVOLUME_H
#define M_SHADOWVOLUME_H

#include "matrix4.h"
#include "renderable.h"
#include "material.h"
#include "renderdata.h"
#include "vertexdeclaration.h"
#include "hardwarebuffer.h"
#include "types.h"
#include "subentity.h"

#include <vector>

namespace Engine
{
	/**
	*   Used for rendering shadow volume for specific randerable.
	*/
	class ShadowVolume:public Renderable
	{
	public:
		friend class ShadowTask;

		typedef std::vector< RefPtr<SubEntity,WeakPtrExtension> > SubEntityVector;

		ShadowVolume();

		~ShadowVolume();

		void Update(const Light* light, const SubEntityVector* rend);

		virtual const MaterialPtr GetMaterial(void) const;

		virtual RenderDataPtr GetRenderData() const;

		virtual const Matrix4<REAL>& GetWorldTransform() const;

		virtual const HardWareBufferPtr GetVertexData() const;

		virtual const HardWareBufferPtr GetIndexData() const;

		virtual const VertexDeclarationPtr GetVertexDeclaration() const;

	private:
		struct EdgeElem
		{
			EdgeElem():vertexIndex(0){}
			EdgeElem(unsigned short ind, const Vector3<REAL>& vert): vertexIndex(ind), vertex(vert){}
			bool operator == (const EdgeElem& rhs){return vertexIndex == rhs.vertexIndex;}

			unsigned short vertexIndex;
			Vector3<REAL> vertex;
		};

		void AddEdge( std::vector<EdgeElem>& edges, EdgeElem v0, EdgeElem v1 );

	private:

		REAL m_extrudeDistance;

		Vector3<REAL> m_lightPos;
		Matrix4<REAL> m_transform;
		MaterialPtr m_material;
		RefPtr<RenderData, WeakPtrExtension> m_renderData;
		RefPtr<VertexDeclaration,WeakPtrExtension> m_vertexDeclaration;
		RefPtr<HardWareBuffer,WeakPtrExtension> m_vertexData;
		RefPtr<HardWareBuffer,WeakPtrExtension> m_indexData;
	};
}

#endif
